home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 7 code / QuickTime / SimpleInMovies / SimpleInPrint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-13  |  25.8 KB  |  878 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. SimpleInMovies
  3.  
  4. Sample programs demonstrating how to open and display
  5. QuickTime™ Movies.
  6.  
  7. SimpleInPrint.c file contains the code printing movie posters.
  8.  
  9. Guillermo A. Ortiz
  10. Macintosh Developer Technical Support
  11.  
  12. 12/03/91 -- Added file and made changes to print movie posters.
  13.  
  14. IMPORTANT NOTE:
  15. This code comes straight from the Develop article (and its code) Meet PrGeneral,
  16. Develop #3 by Pete "Luke" Alexander. All the credit goes to the source. Check Develop
  17. for complete comments.
  18.  
  19. In the other hand blame all problems in the changes that were made in order to make 
  20. it do the things needed in the SimpleInMovies sample.
  21.  
  22.  
  23. ------------------------------------------------------------------------------*/
  24.  
  25. #include <SimpleInMovie.h>
  26.  
  27. extern void    PositionRectInRect(Rect, Rect *, Fixed , Fixed);
  28.  
  29. //  The following extern globals are set up by the Initialize function in SimpleInMovies.c
  30.  
  31. THPrint            gPrRecHdl;
  32. Boolean            gHighResolutionON = false,  
  33.                         gUseDraftBits = false,
  34.                         gCheckForLandscape = false,
  35.                         gDraftBitsHasBeenSet = false,
  36.                         gPrGeneralLives,
  37.                         gLandscapeOpImpl,
  38.                         gDraftBitsOpImpl,
  39.                         gSetRslOpImpl;
  40.  
  41. short            gOriginalDriverVers;
  42.                         
  43. short                      gScale = 1,
  44.                         gMaxDPI = 0,
  45.                         gOriginaliVRes,
  46.                         gOriginaliHRes;
  47.  
  48.  
  49. void noPrGeneralAlert ( void );
  50. Boolean testForPrGeneral ( void );
  51. void saveResolution ( void );
  52. void resetSetRsl ( void );
  53. int setMaxResolution ( void );
  54. void doSetRsl ( void );
  55. void doDraftBits ( void );
  56. void doNODraftBits ( void );
  57. void drawStuff (GrafPtr    prPort, short gScale, PicHandle toPrint);
  58. void copyBitsMyGraph (TPPrPort printPort, PicHandle toPrint);
  59. void comparePrintRecords ( void );
  60. void PresentStyleDialog ( void );
  61. void PrintThis( PicHandle );
  62. void PrintTerminate(void);
  63. void PrintInit(void);
  64. void AlertUser();
  65. void PrintPoster(void);
  66.  
  67. void PrintInit(void)
  68. {
  69. short myPrintErr;
  70.  
  71. /**
  72.         We will assume at this point that all of PrGeneral's opcodes are supported.
  73.         When we make a call for a particular opcode, we will check to make sure that 
  74.         the opcode is supported.  If it is NOT, the appropraite flag will be set to false
  75.         and that opcode will not be called until the printer driver is changed.
  76.     **/
  77.     gLandscapeOpImpl = true;
  78.     gDraftBitsOpImpl = true;
  79.     gSetRslOpImpl = true;
  80.  
  81.     /**
  82.         Create & initialize the print record....
  83.      **/
  84.      myPrintErr = 0;
  85.      gPrRecHdl = (THPrint) NewHandle(sizeof(TPrint));
  86.  
  87.  
  88.      if (MemError() == noErr && gPrRecHdl != nil)
  89.       {
  90.        PrOpen(); 
  91.         if (PrError() == noErr)
  92.           {
  93.            PrintDefault (gPrRecHdl);
  94.     
  95.            // We need to save the version number of the current printer driver.  This will enable
  96.            // us to compare the version of the printer driver when the user chooses a different
  97.            // printer driver via the Chooser.  This important because some earlier versions of 
  98.            // Apple's printers drivers did not support PrGeneral.  Which is the case for the 
  99.            // ImageWriter v2.5 and LaserWriter v4.0 and earlier.
  100.  
  101.            gOriginalDriverVers = PrDrvrVers ();
  102.            
  103.            if (PrError () == noErr)
  104.              gPrGeneralLives = testForPrGeneral ();  // Check to see if the current printer driver 
  105.             else myPrintErr = PrError ();             // supports PrGeneral and set the global flag...
  106.            }
  107.         else myPrintErr = PrError ();    // Grab the error before we close the Print Manager
  108.        PrClose();
  109.       
  110.        if (myPrintErr != 0)  
  111.          AlertUser ();
  112.       }
  113.      else  AlertUser ();
  114. }
  115.  
  116. /* Clean up and exit. */
  117.  
  118. #pragma segment Main
  119. void PrintTerminate()
  120. {
  121.     if (gPrRecHdl != nil)    
  122.       DisposHandle ((Handle) gPrRecHdl);     // Dispose of the print record
  123.     
  124. } /*Terminate*/
  125.  
  126.  
  127. /*    Display an alert that tells the user an error occurred.
  128.     This routine is used as an ultimate bail-out for serious errors that prohibit
  129.     the continuation of the application. Errors that do not require the termination
  130.     of the application should be handled in a different manner. Error checking and
  131.     reporting has a place even in the simplest application. The error number is used
  132.     to index an 'STR#' resource so that a relevant message can be displayed. */
  133.  
  134. #pragma segment Main
  135. void AlertUser()
  136. {
  137.     short        itemHit;
  138.  
  139.     SetCursor(&qd.arrow);
  140.     itemHit = Alert(rUserAlert, nil);
  141. } /* AlertUser */
  142.  
  143. //------ noPrGeneralAlert -----------------------------------------------------------
  144. //
  145. //  Display the alert that tells the user that PrGeneral is not available
  146. //  for the currently selected printer driver...
  147. //
  148.  
  149. void noPrGeneralAlert ()
  150. {
  151.     short        itemHit;
  152.  
  153.     SetCursor(&qd.arrow);
  154.     
  155.     itemHit = NoteAlert(rNOPrGeneralAlert, nil);
  156. }  //  end of noPrGeneralAlert
  157.  
  158.  
  159.  
  160.  
  161. //------ testForPrGeneral -----------------------------------------------------------
  162. //
  163. //  We want to determine if PrGeneral is available.  If it is not, the printer driver
  164. //  will return resNotFound in PrError.  We will then clear the error in PrError with
  165. //  PrSetError (0) and proceed with printing without PrGeneral's opcodes.  If we did not
  166. //  clear the error, you would receive the error in PrError when it was checked, thereby
  167. //  preventing your app from printing.
  168.  
  169. Boolean testForPrGeneral ()
  170. {
  171.       TGetRotnBlk    GetRotRec;
  172.       short          printErr = 0;
  173.   
  174.     GetRotRec.iOpCode = getRotnOp;    // We will test for PrGeneral with the landscape opcode...
  175.     GetRotRec.hPrint = gPrRecHdl;
  176.  
  177.       PrGeneral ((Ptr) &GetRotRec);    
  178.   
  179.       printErr = PrError ();
  180.   
  181.       if (printErr == noErr)            //  PrGeneral is supported by the current driver...
  182.       return (true);
  183.       else 
  184.       {
  185.        if (printErr == resNotFound)
  186.          {
  187.            PrSetError (noErr);        // Since PrGeneral is not available, we want to clear PrError,
  188.            noPrGeneralAlert ();       // which will enable your app to keep printing without
  189.            return (false);            // PrGeneral's opcodes...
  190.          }
  191.        else 
  192.         {
  193.           PrClose ();
  194.           AlertUser ();               // Another type of print error occurred, therefore AlertUser
  195.         }
  196.       }
  197. }  //  end of testForPrGeneral
  198.  
  199.  
  200.  
  201. //------ saveResolution -------------------------------------------------------------
  202. //
  203. //    We need to save the original resolution of the current printer driver, which will
  204. //    enable us to reset the resolutiuon if the user turns the "high resolution" printing
  205. //    menu item "off".
  206. //
  207.  
  208. void saveResolution ()
  209. {
  210.     gOriginaliVRes = (**gPrRecHdl).prInfo.iVRes;
  211.     gOriginaliHRes = (**gPrRecHdl).prInfo.iHRes;
  212. }
  213.  
  214.  
  215.  
  216. //------ resetSetRsl ----------------------------------------------------------------
  217. //
  218. //    resetSetRsl will reset the resolution of the print handle, back to it's orginal 
  219. //    before using the SetRsl opcode.  If the user has not changed the printer, we 
  220. //    will reset the resolution of the printer driver with a call to the SetRsl opcode 
  221. //  with the orginal resolutions that were saved by the function saveResolution. If 
  222. //  the user has selected a different printer via the Chooser, we will call PrintDefault 
  223. //  on our print record.  
  224. //
  225.  
  226. void resetSetRsl ()
  227. {
  228.     TSetRslBlk    setResRec;
  229.     THPrint     localPrRecHdl;
  230.     short        latestDriverVers;
  231.  
  232.     //  Create a "new" print record to compare with...
  233.     
  234.     localPrRecHdl = (THPrint) NewHandle(sizeof(TPrint));
  235.     if (MemError() == noErr && localPrRecHdl != nil)
  236.     {
  237.         PrintDefault (localPrRecHdl);
  238.     
  239.         latestDriverVers = PrDrvrVers ();
  240.     
  241.         //     We need to determine if the user changed the printer driver via Chooser.  
  242.         //    Which would be a problem because the resolutions might not match across 
  243.         //    different printer drivers. We also check to see if the version number has 
  244.         //    changed, which will insure that the user did not change the printer driver
  245.         //    to a different printer driver version.  This is important, because earlier
  246.         //    versions of the ImageWriter (i.e. before v2.5) did not support PrGeneral.
  247.         //  If they have changed the printer driver, call PrintDefault on our global print 
  248.         //  record handle to update it.
  249.         
  250.         if ((((**gPrRecHdl).prStl.wDev) >> 8) == (((**localPrRecHdl).prStl.wDev) >> 8)
  251.              || (latestDriverVers == gOriginalDriverVers))
  252.           {
  253.             //    Reset the print record to the original resolutions...
  254.             
  255.             setResRec.iOpCode = setRslOp;
  256.             setResRec.hPrint = gPrRecHdl;
  257.     
  258.             setResRec.iXRsl = gOriginaliHRes;
  259.             setResRec.iYRsl = gOriginaliVRes;
  260.             
  261.              
  262.             // We do not need to check any PrGeneral errors. Why? We know that this opcode 
  263.             // is supported and we are not using an unsupported resolution...
  264.             
  265.             PrGeneral ((Ptr)(&setResRec));     
  266.     
  267.             gScale = 1;
  268.             gMaxDPI = gOriginaliHRes;                
  269.     
  270.             if (PrError () != noErr)
  271.              {
  272.                PrClose ();          //  We received an error in PrError after calling PrGeneral.
  273.                AlertUser ();        //  Therefore, close the Print Manager and alert the user.
  274.              }
  275.           }
  276.          else  PrintDefault (gPrRecHdl);    
  277.             
  278.         if (localPrRecHdl != nil)  DisposHandle((Handle) localPrRecHdl);
  279.     }
  280.  
  281.         // An error occurred allocating new print record, close the Print Manager and alert the user
  282.     else
  283.     {
  284.         PrClose ();
  285.         AlertUser();
  286.     }
  287.  
  288. }    //  end of resetSetRsl
  289.  
  290.  
  291.  
  292.  
  293. //------ setMaxResolution -----------------------------------------------------------
  294. //
  295. //    setMaxResolution will find the highest "square" resolution supported by the currently 
  296. //    selected printer driver and set the Print Manager's GrafPort to this resolution. 
  297. //    This will enable high resolution printing using the standard Quickdraw calls.  We
  298. //    will return the resolution that is found by our calls to GetRslData.  If the 
  299. //    GetRslData and/or SetRsl opcodes are not supported by the currently selected printer
  300. //    driver, we will return 0.  Which tells the calling function that it must use a
  301. //    scale factor of 1 and assume no SetRsl support
  302. //
  303.  
  304. int setMaxResolution ()
  305. {
  306.      int            resIndex;
  307.      
  308.      TGetRslBlk    getResRec;
  309.      TSetRslBlk    setResRec;
  310.  
  311.     //    Save the current resolution values from the iVRes and iHres fields from 
  312.     //  the PrJob record; which enables us to reset the print handle with the original 
  313.     //  values, if the user un-checks the "high resolution" menu item.
  314.     
  315.     saveResolution ();   
  316.  
  317.      getResRec.iOpCode = getRslDataOp;
  318.      PrGeneral ((Ptr)(&getResRec));    
  319.      
  320.      //    We have an array of possible resolutions.
  321.     //  After checking for errors, we loop through each resolution 
  322.      //    range record looking for the highest resolution available, where x and
  323.      //    y are equal. This loop makes no assumptions about the order of the 
  324.      //    resolution records. Find the maximum resolution supported by the current selected device.
  325.      //    Some devices support non-square aspect ratios (i.e. x-res != y-res), we
  326.      //    need to find the largest "square" resolution supported.  The last rgRslRec is
  327.     //  the "highest" supported resolution record for all of the Apple printer drivers.
  328.     
  329.      if (getResRec.iError == noErr && PrError() == noErr)
  330.        {
  331.         for (resIndex = 0; resIndex < getResRec.iRslRecCnt ; resIndex++)
  332.            {
  333.              if ( getResRec.rgRslRec[resIndex].iXRsl ==
  334.                    getResRec.rgRslRec[resIndex].iYRsl && 
  335.                    getResRec.rgRslRec[resIndex].iXRsl > gMaxDPI)
  336.                   
  337.                gMaxDPI = getResRec.rgRslRec[resIndex].iYRsl;
  338.             }
  339.            
  340.         //  We now have the desired resolution. If it is not 0, then we
  341.        //  use the SetRsl opcode to set the resolution.
  342.  
  343.        if (gMaxDPI != 0 && gPrRecHdl != nil)
  344.            {
  345.             setResRec.iOpCode = setRslOp;
  346.             setResRec.hPrint = gPrRecHdl;
  347.  
  348.             setResRec.iXRsl = gMaxDPI;
  349.             setResRec.iYRsl = gMaxDPI;
  350.          
  351.              PrGeneral ((Ptr)(&setResRec));    
  352.            }
  353.       }
  354.      //     If the current printer driver does NOT support GetRslData set the flag
  355.      //  and return 0, which tells the calling function to use a scale factor of 1.
  356.      
  357.      else if (getResRec.iError == OpNotImpl)   
  358.            {
  359.              gSetRslOpImpl = false;
  360.              return (0);
  361.            }
  362.           else AlertUser (); 
  363.  
  364.  
  365.      //    If our call to SetRsl worked return the "new" resolution, otherwise
  366.     //    check to see if this opcode is implemented.  If it is not return 0 
  367.     //    and set our SetRslOpImpl flag to false.  
  368.     
  369.     if (setResRec.iError == noErr && PrError() == noErr && gMaxDPI != 0)
  370.           return (gMaxDPI);
  371.     else if (setResRec.iError == OpNotImpl && PrError() == noErr)
  372.            {
  373.              gSetRslOpImpl = false;
  374.              return (0);
  375.            }
  376.          else return (0);
  377.  
  378. }    //  end of setMaxResolution
  379.  
  380.  
  381.  
  382.     
  383. //------ doSetRsl -------------------------------------------------------------------
  384. //
  385. //  doSetRsl is the calling function that calls setMaxResolution.  setMaxResolution
  386. //    will return the maximum resolution that is supported by the current printer
  387. //    driver.  With this device resolution (deviceRes), we will then determine the scale
  388. //    factor that must be used on all of our coordinates and font sizes, otherwise
  389. //    we will receive "micro" text and images.  If setMaxresolution returns 0, it means 
  390. //    that SetRsl and GetRslData are not supported or an error occurred.  We will then
  391. //    use a scale factor of 1.
  392. //
  393.  
  394. void doSetRsl ()
  395. {
  396.     short        deviceRes;
  397.     GrafPtr        oldPort;
  398.     
  399.     GetPort (&oldPort);
  400.  
  401.     deviceRes = setMaxResolution ();
  402.      
  403.     //    If deviceRes is not zero, we will determine the scale factor that
  404.     //    MUST be used on all of our coordinates and font sizes.  If we do 
  405.     //    NOT scale these items, we will get the "micro" text and images...
  406.     
  407.     if (deviceRes != 0) gScale = deviceRes / MacScreenRes;
  408.  
  409.     SetPort (oldPort);
  410.  
  411. }    //     end of doSetRsl
  412.  
  413.  
  414.  
  415.  
  416. //------ doDraftBits ----------------------------------------------------------------
  417. //
  418. //    doDraftBits will set the draftBitsOp opcode for the current printer driver.  If the 
  419. //    current printer driver does NOT support this opcode, we will set the gDraftBitsOpImpl
  420. //    flag to false which will prevent this function from being called.  If any error occurs,
  421. //    we will alert the user via the AlertUser function.
  422. //
  423.  
  424. void doDraftBits ()
  425. {
  426.     TDftBitsBlk        draftBitsBlk;
  427.  
  428.     gDraftBitsHasBeenSet = true;
  429.  
  430.     //  Set the draftBitsOp and update the contents of the print handle.
  431.     
  432.     draftBitsBlk.iOpCode = draftBitsOp;
  433.     draftBitsBlk.hPrint = gPrRecHdl;
  434.     PrGeneral((Ptr) &draftBitsBlk);
  435.  
  436.     //  The draftBits opcode is NOT supported by the current printer driver,
  437.     //  therefore we will set the draftBits opcode implemented flag to false.
  438.     //  Which will prevent this function from being called until a new printer 
  439.     //  is selected via the Chooser.  If another type of error occurred report
  440.     //  it to the user via AlertUser.
  441.  
  442.     if (draftBitsBlk.iError == OpNotImpl && PrError() == noErr)
  443.       gDraftBitsOpImpl  = false; 
  444.     else if (draftBitsBlk.iError != noErr || PrError() != noErr)
  445.            AlertUser ();
  446.      
  447. }  // end of doDraftBits
  448.  
  449.  
  450.  
  451.  
  452. //------ doNODraftBits ---------------------------------------------------------------
  453. //
  454. //    doNODraftBits will undo the call to set the draftBitsOp opcode.  This function can
  455. //  NOT be called if doDraftBits was not called or this opcode is not supported by the 
  456. //    current printer driver.  This function behaves in the same manner as described above
  457. //  for doDraftBits.
  458. //
  459.  
  460. void doNODraftBits ()
  461. {
  462.     TDftBitsBlk        draftBitsBlk;
  463.  
  464.     draftBitsBlk.iOpCode = noDraftBitsOp;
  465.     draftBitsBlk.hPrint = gPrRecHdl;
  466.     PrGeneral((Ptr) &draftBitsBlk);
  467.  
  468.     if (draftBitsBlk.iError != noErr || PrError() != noErr)
  469.        AlertUser ();
  470.  
  471. }  // end of doNODraftBits
  472.  
  473.  
  474.  
  475.  
  476. //------ ShowLandscapeResults --------------------------------------------------------
  477. //
  478. //    This routine will show the results via a dialog of the IsLandscapeSet function.
  479. //
  480.  
  481. void ShowLandscapeResults (Boolean result)
  482.  
  483. {
  484.       short            itemHit;
  485.       StringHandle    displayMessage;
  486.       Str255            displayMessageString;
  487.   
  488.       SetCursor(&qd.arrow);
  489.   
  490.       if (result)  
  491.       displayMessage = GetString (201);
  492.     else
  493.       displayMessage = GetString (202);
  494.     
  495.     
  496.        if (displayMessage != nil)
  497.       BlockMove(*displayMessage, &displayMessageString, (long)*displayMessage[0]+1L);
  498.      else
  499.        AlertUser();
  500.        
  501.     ParamText (displayMessageString, "\p ", "\p ", "\p ");
  502.     
  503.     itemHit = NoteAlert(rLandscapeAlert, nil);
  504.     
  505. }    //  end of ShowLandscapeResults
  506.  
  507.  
  508.  
  509.  
  510. //------ IsLandscapeSet -------------------------------------------------------------
  511. //
  512. //    IsLandscapeSet will determine if the user has selected landscape orientation 
  513. //    from the Style dialog. If the user has selected landscape orientation, we will 
  514. //    return "true" to the calling function. Otherwise, return "false".
  515. //
  516.  
  517. void IsLandscapeSet (THPrint thePrRecHdl)
  518.  
  519. {
  520.        TGetRotnBlk    GetRotRec;
  521.     
  522.        GetRotRec.iOpCode = getRotnOp;
  523.       GetRotRec.hPrint = thePrRecHdl;
  524.  
  525.       PrGeneral ((Ptr) &GetRotRec);    
  526.      
  527.     //  If the landscape opcode is NOT implemented by the current printer driver,
  528.     //  set the flag to true.  This flag will preent the calling of this function
  529.     //  until the printer driver is changed...
  530.  
  531.     if (GetRotRec.iError == OpNotImpl)
  532.       gLandscapeOpImpl = false;
  533.       
  534.       
  535.     //    We now have the result from our call to PrGeneral, but we check all
  536.     //    known errors to make sure that PrGeneral was successful and there
  537.     //    have not been any errors encountered from printing land.
  538.  
  539.     if (GetRotRec.iError == noErr && PrError() == noErr && GetRotRec.fLandscape)
  540.        ShowLandscapeResults (true);
  541.     else if (GetRotRec.iError != OpNotImpl)
  542.            ShowLandscapeResults (false);
  543.  
  544. }    //  end of IsLandscapeSet
  545.  
  546.  
  547.  
  548.  
  549. //------ drawStuff ------------------------------------------------------------------
  550. //
  551. //    drawStuff will create the graph and draw it directly to the current port that is
  552. //    passed in via the prPort variable. It will draw all of the coordinates and font
  553. //    sizes at the prScale value.  For example, on the ImageWriter, the scaling is 2X 
  554. //  the screen. On the ImageWriter LQ, three times and on the LaserWriter, four times.
  555. //    TBy using a scale factor ensures that you do NOT print "micro" images or text when 
  556. //    the SetRsl opcode is used.
  557. //
  558. //
  559.  
  560. void drawStuff ( prPort, prScale, toPrint)
  561.  
  562. GrafPtr        prPort;
  563. short        prScale;
  564. PicHandle    toPrint;
  565. {
  566. #pragma unused (prScale)
  567.  
  568.     Rect        graphRect, pictRect;
  569.  
  570.  
  571.     CGrafPtr    currPort;
  572.     GDHandle    currDev;
  573.     
  574.  
  575.     GetGWorld (&currPort, &currDev);
  576.  
  577.     SetGWorld ((CGrafPtr) prPort, currDev);
  578.  
  579.     SetRect (&graphRect, 0, 0, 500, 300);
  580.     
  581.     EraseRect (&(prPort->portRect));
  582.     
  583.     pictRect = (*toPrint)->picFrame;
  584.     
  585.     PositionRectInRect(prPort->portRect, &pictRect, FixRatio (1, 2),
  586.                        FixRatio (1, 3));
  587.  
  588.     
  589.     DrawPicture(toPrint, &pictRect);
  590.     
  591.    SetGWorld (currPort, currDev);
  592.  
  593. }    // end of drawStuff
  594.  
  595.  
  596.  
  597.  
  598. //------ copyBitsMyGraph -------------------------------------------------------------
  599. //
  600. //    copyBitsMyGraph will create a off-screen world with a call to 32-bit QuickDraw's
  601. //  NewGWorld.  We check to make sure that 32-bit QuickDraw is present BEFORE this 
  602. //  function is called.  We will then draw directly into the the off-screen world with a call
  603. //    to drawStuff.  CopyBits will then be used to copy the contents of the off-screen world
  604. //    into the printer's GrafPort.  Remember, when you use the DraftBits opcode, it will 
  605. //  only print text, bitmaps, and pixmaps.  If we did NOT use the CopyBits call, only the 
  606. //    heading of the graph would be printed...
  607. //
  608.  
  609. void copyBitsMyGraph (TPPrPort printPort, PicHandle toPrint)
  610. {
  611.     Rect        graphRect;
  612.     QDErr        QDError;
  613.     GDHandle    currDev;
  614.     CGrafPtr    currPort;
  615.     GWorldPtr    myDrawingPort;
  616.  
  617.  
  618.     GetGWorld (&currPort, &currDev);
  619.         
  620.     SetRect (&graphRect, 0, 0, 500 * gScale, 300 * gScale);
  621.     
  622.     QDError = NewGWorld(&myDrawingPort, 1, &graphRect, nil, nil, 0);
  623.     
  624.     if (QDError == noErr)
  625.       {
  626.         if (!LockPixels (myDrawingPort->portPixMap))
  627.           AlertUser ();
  628.         
  629.         //  Draw the graph into the off-screen world...
  630.           drawStuff (myDrawingPort, gScale, toPrint);
  631.         
  632.         
  633.         //  Set the port to the printer's GrafPort and CopyBits the off-screen
  634.         //  world into the printer's GrafPort.
  635.         
  636.         SetPort (&(printPort->gPort));
  637.           CopyBits ((BitMap *) &myDrawingPort->portPixMap, &(printPort->gPort.portBits), 
  638.                   &myDrawingPort->portRect, &myDrawingPort->portRect, srcCopy, nil);
  639.         UnlockPixels (myDrawingPort->portPixMap);
  640.         
  641.       }
  642.      else AlertUser ();
  643.     
  644.     if (myDrawingPort != nil)
  645.          DisposeGWorld (myDrawingPort);
  646.  
  647.     SetGWorld (currPort, currDev);
  648.     
  649. }    // end of copyBitsMyGraph
  650.  
  651.  
  652.  
  653.  
  654.  
  655. //------ comparePrintRecords ---------------------------------------------------------
  656. //
  657. //  We need to determine if the print has changed, since the last time we
  658. //  called the PageSetup or Print Job dialog.  If it has, we want to update the print
  659. //    record with the PrGeneral selections from the PrGeneral menu.  But, before we call
  660. //  PrGeneral to set the requested opcodes, we will call testForPrGeneral to make sure
  661. //  that it is supported by the "new" printer driver.  We only worry about the SetRsl and
  662. //  DraftBits opcodes at this point, because they effect the appearance of the PageSetup 
  663. //  and Print Job, if PrGeneral is available.
  664. //
  665.  
  666. void comparePrintRecords ()
  667. {
  668.     THPrint     localPrRecHdl;
  669.     short        latestDriverVers;
  670.     
  671.  
  672.     // Create a new print record with default settings
  673.     
  674.     localPrRecHdl = (THPrint) NewHandle(sizeof(TPrint));
  675.     if (MemError() == noErr && localPrRecHdl != nil)
  676.     {
  677.         PrintDefault (localPrRecHdl);
  678.     
  679.         latestDriverVers = PrDrvrVers ();
  680.     
  681.         //  This is an example of the right place to use wDev. We are only using wDev to 
  682.         //  determine, if the print records are the same type. NOT to check for specific
  683.         //  functionality which would be a bad idea for compatibility with unknown printers.
  684.         
  685.         if (PrError () == noErr)
  686.          {
  687.           if ((((**gPrRecHdl).prStl.wDev) >> 8) != (((**localPrRecHdl).prStl.wDev) >> 8)
  688.                || (latestDriverVers != gOriginalDriverVers))
  689.            { 
  690.              //  Set the print record to default settings for the "new" printer...
  691.     
  692.              PrintDefault (gPrRecHdl);
  693.             
  694.              //  Reset the value of gOriginalDriverVers
  695.     
  696.              gOriginalDriverVers = latestDriverVers;
  697.     
  698.     
  699.              //  Reset gMaxDPI to enable the loop in setMaxResolution to find the correct 
  700.              //  maximum resolution
  701.     
  702.              gMaxDPI = 0;
  703.              
  704.              
  705.              //  Reset all of the opcode implementation flags.  We now have a new printer
  706.              //  driver, therefore we need to determine which opcodes are supported.
  707.              
  708.              gLandscapeOpImpl = true;
  709.              gDraftBitsOpImpl = true;
  710.              gSetRslOpImpl = true;
  711.              
  712.              
  713.              // Test to determine, if the "new" printer driver supports PrGeneral before
  714.              // updating the print record with the requested PrGeneral opcodes...
  715.     
  716.              if (PrError () == noErr)
  717.                 gPrGeneralLives = testForPrGeneral ();
  718.              else AlertUser ();  
  719.     
  720.              
  721.              // Call the appropriate PrGeneral opcodes, determined by the PrGeneral menu...
  722.     
  723.              if (PrError () == noErr && gPrGeneralLives)
  724.                {
  725.                 if (gUseDraftBits && gDraftBitsOpImpl)  doDraftBits();
  726.             
  727.                 if (gHighResolutionON && gSetRslOpImpl)  doSetRsl();     
  728.                }
  729.            }
  730.          
  731.            if (localPrRecHdl != nil)  DisposHandle((Handle) localPrRecHdl);
  732.          }
  733.     
  734.         // An error has occurred, close the Print Manager and alert the user    
  735.         
  736.         else   
  737.           {
  738.            PrClose ();
  739.            if (localPrRecHdl != nil)  DisposHandle((Handle) localPrRecHdl);
  740.            AlertUser ();
  741.           }
  742.     }
  743.     
  744.     // An error occurred allocating new print record, close the Print Manager and alert the user
  745.     else
  746.     {
  747.         PrClose ();
  748.         AlertUser();
  749.     }
  750.  
  751. }    //  end of comparePrintRecords
  752.  
  753.  
  754.  
  755.  
  756. //------ PresentStyleDialog ----------------------------------------------------------
  757. //
  758. //  We will present the PageSetup dialog requested by the user, but we want to make sure
  759. //  that the printer driver has not changed.  Why? If the user has changed the printer 
  760. //  driver via the Chooser, we want to update the print record with the requested
  761. //  PrGeneral opcodes, if the "new" (current) printer driver supports PrGeneral.
  762. //  Remember, the SetRsl and DraftBits opcodes change the appearence of the Page Setup 
  763. //  dialog, therefore we want to make the PrGeneral calls before presenting the dialog.
  764. //
  765.  
  766. void PresentStyleDialog ()
  767. {
  768.     if ( gPrRecHdl ) 
  769.      {
  770.         PrOpen();
  771.         
  772.         // A print error occurred, close up the Print Manager and notify the user...
  773.     
  774.         if (PrError () != noErr)
  775.           {
  776.             PrClose();
  777.             AlertUser ();
  778.           }
  779.          else 
  780.            {
  781.             // Check to make sure that the user has not changed the printer driver 
  782.            
  783.             comparePrintRecords ();        
  784.  
  785.             PrStlDialog(gPrRecHdl);
  786.             
  787.             // Check for landscape orientation, if the user has requested the test via
  788.             // the PrGeneral Menu and PrGeneral exists for the current printer driver...
  789.             
  790.             if (gCheckForLandscape && gPrGeneralLives && gLandscapeOpImpl)  
  791.               IsLandscapeSet (gPrRecHdl);
  792.         
  793.             PrClose();
  794.            }
  795.      }
  796.      else AlertUser ();    // The gPrRecHdl is nil and it should not be, alert the user
  797.  
  798. }    //  end of PresentStyleDialog
  799.  
  800.  
  801.  
  802.  
  803. //------ PrintThis -------------------------------------------------------------------
  804. //
  805. //  PrintThis is your basic print loop.  If any error occurs during this function 
  806. //  (i.e. print time) the user will be notified via a call to AlertUser.  But, before we 
  807. //  alert the user, we will call the corresponding close call(s) for all of the open 
  808. //  call(s) (i.e. PrOpenDoc  --> PrCloseDoc) and close up the Print Manager.  For a 
  809. //  complete industrial strength print loop, see Tech Note #161.  
  810. //
  811.  
  812. void PrintThis(PicHandle PICTToPrint)
  813. {
  814.     short            NumberOfPages;
  815.     TPPrPort        printPort;
  816.     OSErr            err;
  817.     short            i;
  818.     TPrStatus         Status;
  819.     GDHandle        currDev;
  820.     CGrafPtr        currPort;
  821.  
  822.     GetGWorld (&currPort, &currDev);
  823.     
  824.     if ( gPrRecHdl ) {
  825.         PrOpen();
  826.         if ( PrError() == noErr ) { 
  827.         
  828.           // Determine if the printer driver has changed...
  829.           
  830.           comparePrintRecords ();     
  831.             
  832.           if ( PrJobDialog(gPrRecHdl)) 
  833.             
  834.             if ( PrError() == noErr ) {
  835.                           
  836.               NumberOfPages = (**gPrRecHdl).prJob.iCopies;
  837.                         
  838.               printPort = PrOpenDoc(gPrRecHdl,nil,nil);
  839.                         
  840.               if ( PrError() == noErr ) {
  841.                 for ( i = 1; i <= NumberOfPages; i++) {
  842.                    PrOpenPage(printPort,nil);
  843.                                 
  844.                    if ( !(err = PrError()) ) {
  845.                     
  846.                     //  If the user has selected the DraftBits menu item,
  847.                     //  we will call copyBitsMyGraph, which will ensure that 
  848.                     //  our graph will be printed "draft" on the ImageWritter. If
  849.                     //  we just called drawStuff all of the time, the graph would 
  850.                     //  NOT print when "draft" printing was selected.
  851.  
  852.                     if (gUseDraftBits)
  853.                       copyBitsMyGraph (printPort, PICTToPrint);
  854.                     else drawStuff (&(printPort->gPort), gScale, PICTToPrint);
  855.                     }
  856.                                 
  857.                    PrClosePage(printPort);
  858.                    }
  859.                    PrCloseDoc(printPort);
  860.                 }
  861.                         
  862.              if ((**gPrRecHdl).prJob.bJDocLoop == bSpoolLoop && PrError() == noErr)
  863.                 PrPicFile(gPrRecHdl,nil,nil,nil,&Status);
  864.                         
  865.              err = PrError();
  866.             
  867.            PrClose();
  868.            if ( err )
  869.              AlertUser();
  870.             }
  871.           }
  872.         }
  873.     
  874.     SetGWorld (currPort, currDev);
  875.     
  876. }    //  end of PrintThis
  877.  
  878.